<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Morphological Transformations</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d5/d10/tutorial_js_root.html">OpenCV.js Tutorials</a></li><li class="navelem"><a class="el" href="../../d2/df0/tutorial_js_table_of_contents_imgproc.html">Image Processing</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Morphological Transformations </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goal </h2>
<ul>
<li>We will learn different morphological operations like Erosion, Dilation, Opening, Closing etc.</li>
<li>We will learn different functions like : <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb" title="Erodes an image by using a specific structuring element. ">cv.erode()</a></b>, <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c" title="Dilates an image by using a specific structuring element. ">cv.dilate()</a></b>, <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga67493776e3ad1a3df63883829375201f" title="Performs advanced morphological transformations. ">cv.morphologyEx()</a></b> etc.</li>
</ul>
<h2>Theory </h2>
<p>Morphological transformations are some simple operations based on the image shape. It is normally performed on binary images. It needs two inputs, one is our original image, second one is called <b>structuring element</b> or <b>kernel</b> which decides the nature of operation. Two basic morphological operators are Erosion and Dilation. Then its variant forms like Opening, Closing, Gradient etc also comes into play. We will see them one-by-one with help of following image:</p>
<div class="image">
<img src="../../shape.jpg" alt="shape.jpg"/>
<div class="caption">
image</div></div>
 <h3>1. Erosion</h3>
<p>The basic idea of erosion is just like soil erosion only, it erodes away the boundaries of foreground object (Always try to keep foreground in white). So what it does? The kernel slides through the image (as in 2D convolution). A pixel in the original image (either 1 or 0) will be considered 1 only if all the pixels under the kernel is 1, otherwise it is eroded (made to zero).</p>
<p>So what happends is that, all the pixels near boundary will be discarded depending upon the size of kernel. So the thickness or size of the foreground object decreases or simply white region decreases in the image. It is useful for removing small white noises (as we have seen in colorspace chapter), detach two connected objects etc.</p>
<p>We use the function: <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb" title="Erodes an image by using a specific structuring element. ">cv.erode</a> (src, dst, kernel, anchor = new <a class="el" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">cv.Point</a>(-1, -1), iterations = 1, borderType = <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838" title="iiiiii|abcdefgh|iiiiiii with some specified i ">cv.BORDER_CONSTANT</a>, borderValue = <a class="el" href="../../d4/d86/group__imgproc__filter.html#ga94756fad83d9d24d29c9bf478558c40a" title="returns &quot;magic&quot; border value for erosion and dilation. It is automatically transformed to Scalar::all...">cv.morphologyDefaultBorderValue()</a>)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>input image; the number of channels can be arbitrary, but the depth should be one of cv.CV_8U, cv.CV_16U, cv.CV_16S, cv.CV_32F or cv.CV_64F. </td></tr>
    <tr><td class="paramname">dst</td><td>output image of the same size and type as src. </td></tr>
    <tr><td class="paramname">kernel</td><td>structuring element used for erosion. </td></tr>
    <tr><td class="paramname">anchor</td><td>position of the anchor within the element; default value new <a class="el" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">cv.Point</a>(-1, -1) means that the anchor is at the element center. </td></tr>
    <tr><td class="paramname">iterations</td><td>number of times erosion is applied. </td></tr>
    <tr><td class="paramname">borderType</td><td>pixel extrapolation method(see <a class="el" href="../../d2/de8/group__core__array.html#ga209f2f4869e304c82d07739337eae7c5">cv.BorderTypes</a>). </td></tr>
    <tr><td class="paramname">borderValue</td><td>border value in case of a constant border</td></tr>
  </table>
  </dd>
</dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_morphological_ops_erode.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>2. Dilation</h3>
<p>It is just opposite of erosion. Here, a pixel element is '1' if atleast one pixel under the kernel is '1'. So it increases the white region in the image or size of foreground object increases. Normally, in cases like noise removal, erosion is followed by dilation. Because, erosion removes white noises, but it also shrinks our object. So we dilate it. Since noise is gone, they won't come back, but our object area increases. It is also useful in joining broken parts of an object.</p>
<p>We use the function: <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c" title="Dilates an image by using a specific structuring element. ">cv.dilate</a> (src, dst, kernel, anchor = new <a class="el" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">cv.Point</a>(-1, -1), iterations = 1, borderType = <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838" title="iiiiii|abcdefgh|iiiiiii with some specified i ">cv.BORDER_CONSTANT</a>, borderValue = <a class="el" href="../../d4/d86/group__imgproc__filter.html#ga94756fad83d9d24d29c9bf478558c40a" title="returns &quot;magic&quot; border value for erosion and dilation. It is automatically transformed to Scalar::all...">cv.morphologyDefaultBorderValue()</a>)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>input image; the number of channels can be arbitrary, but the depth should be one of cv.CV_8U, cv.CV_16U, cv.CV_16S, cv.CV_32F or cv.CV_64F. </td></tr>
    <tr><td class="paramname">dst</td><td>output image of the same size and type as src. </td></tr>
    <tr><td class="paramname">kernel</td><td>structuring element used for dilation. </td></tr>
    <tr><td class="paramname">anchor</td><td>position of the anchor within the element; default value new <a class="el" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">cv.Point</a>(-1, -1) means that the anchor is at the element center. </td></tr>
    <tr><td class="paramname">iterations</td><td>number of times dilation is applied. </td></tr>
    <tr><td class="paramname">borderType</td><td>pixel extrapolation method(see <a class="el" href="../../d2/de8/group__core__array.html#ga209f2f4869e304c82d07739337eae7c5">cv.BorderTypes</a>). </td></tr>
    <tr><td class="paramname">borderValue</td><td>border value in case of a constant border</td></tr>
  </table>
  </dd>
</dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_morphological_ops_dilate.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>3. Opening</h3>
<p>Opening is just another name of <b>erosion followed by dilation</b>. It is useful in removing noise.</p>
<p>We use the function: <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga67493776e3ad1a3df63883829375201f" title="Performs advanced morphological transformations. ">cv.morphologyEx</a> (src, dst, op, kernel, anchor = new <a class="el" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">cv.Point</a>(-1, -1), iterations = 1, borderType = <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838" title="iiiiii|abcdefgh|iiiiiii with some specified i ">cv.BORDER_CONSTANT</a>, borderValue = <a class="el" href="../../d4/d86/group__imgproc__filter.html#ga94756fad83d9d24d29c9bf478558c40a" title="returns &quot;magic&quot; border value for erosion and dilation. It is automatically transformed to Scalar::all...">cv.morphologyDefaultBorderValue()</a>)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>source image. The number of channels can be arbitrary. The depth should be one of cv.CV_8U, cv.CV_16U, cv.CV_16S, cv.CV_32F or cv.CV_64F </td></tr>
    <tr><td class="paramname">dst</td><td>destination image of the same size and type as source image. </td></tr>
    <tr><td class="paramname">op</td><td>type of a morphological operation, (see <a class="el" href="../../d4/d86/group__imgproc__filter.html#ga7be549266bad7b2e6a04db49827f9f32" title="type of morphological operation ">cv.MorphTypes</a>). </td></tr>
    <tr><td class="paramname">kernel</td><td>structuring element. It can be created using <a class="el" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc" title="Returns a structuring element of the specified size and shape for morphological operations. ">cv.getStructuringElement</a>. </td></tr>
    <tr><td class="paramname">anchor</td><td>anchor position with the kernel. Negative values mean that the anchor is at the kernel center. </td></tr>
    <tr><td class="paramname">iterations</td><td>number of times dilation is applied. </td></tr>
    <tr><td class="paramname">borderType</td><td>pixel extrapolation method(see <a class="el" href="../../d2/de8/group__core__array.html#ga209f2f4869e304c82d07739337eae7c5">cv.BorderTypes</a>). </td></tr>
    <tr><td class="paramname">borderValue</td><td>border value in case of a constant border. The default value has a special meaning.</td></tr>
  </table>
  </dd>
</dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_morphological_ops_opening.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>4. Closing</h3>
<p>Closing is reverse of Opening, <b>Dilation followed by Erosion</b>. It is useful in closing small holes inside the foreground objects, or small black points on the object.</p>
<h2>Try it </h2>
<p> 
<iframe src="../../js_morphological_ops_closing.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>5. Morphological Gradient</h3>
<p>It is the difference between dilation and erosion of an image.</p>
<p>The result will look like the outline of the object.</p>
<h2>Try it </h2>
<p> 
<iframe src="../../js_morphological_ops_gradient.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>6. Top Hat</h3>
<p>It is the difference between input image and Opening of the image.</p>
<h2>Try it </h2>
<p> 
<iframe src="../../js_morphological_ops_topHat.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>7. Black Hat</h3>
<p>It is the difference between the closing of the input image and input image.</p>
<h2>Try it </h2>
<p> 
<iframe src="../../js_morphological_ops_blackHat.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h2>Structuring Element </h2>
<p>We manually created a structuring elements in the previous examples with help of <a class="el" href="../../d3/d63/classcv_1_1Mat.html#a69ae0402d116fc9c71908d8508dc2f09" title="Returns an array of all 1&#39;s of the specified size and type. ">cv.Mat.ones</a>. It is rectangular shape. But in some cases, you may need elliptical/circular shaped kernels. So for this purpose, OpenCV has a function, <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc" title="Returns a structuring element of the specified size and shape for morphological operations. ">cv.getStructuringElement()</a></b>. You just pass the shape and size of the kernel, you get the desired kernel.</p>
<p>We use the function: <b><a class="el" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc" title="Returns a structuring element of the specified size and shape for morphological operations. ">cv.getStructuringElement</a> (shape, ksize, anchor = new <a class="el" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">cv.Point</a>(-1, -1))</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">shape</td><td>element shape that could be one of <a class="el" href="../../d4/d86/group__imgproc__filter.html#gac2db39b56866583a95a5680313c314ad" title="shape of the structuring element ">cv.MorphShapes</a> </td></tr>
    <tr><td class="paramname">ksize</td><td>size of the structuring element. </td></tr>
    <tr><td class="paramname">anchor</td><td>anchor position within the element. The default value [−1,−1] means that the anchor is at the center. Note that only the shape of a cross-shaped element depends on the anchor position. In other cases the anchor just regulates how much the result of the morphological operation is shifted.</td></tr>
  </table>
  </dd>
</dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_morphological_ops_getStructuringElement.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
 </p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:37 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
